#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <dirent.h>
#include <piece/c_lang.h>
#include <windows.h>
#define true 1
int command_status=0;
typedef int (*buitin_fp)(int ,char **);
struct builtin{
	char *name;
	buitin_fp action;
};

int sh_ls ARG {
	char *name=".";
	if(argc>1) name = argv[1];
	DIR *dirp;
	struct dirent *entp=NULL;
	dirp = opendir( name );
	if(dirp==NULL) return 1;
	while(entp = readdir(dirp)){
	  printf("%s\n",entp->d_name);
	}
	return 0;
}
int sh_pwd ARG{
	printf("%s\n",getcwd(NULL,1024));
}
int sh_exit ARG {
	if(argc>1)
	exit(atoi(argv[1]));
	else exit(0);
}
int sh_unlink ARG {
	if(argc<2) {
		puts("unlink:missing argument");
		return 1;
	}
	while(argc--){
	  unlink(argv[argc]);
	}
	return 0;
}
int sh_cd ARG {
	if(argc>1) return chdir(argv[1]);
}
struct builtin list_cmd[]={
	{	"exit",sh_exit},
	{	"cd",sh_cd},
	{	"pwd",sh_pwd},
	//{	"alias",sh_alias},
	//{	"test",sh_test},
	{	"ls",sh_ls},
	//{	"cp",sh_cp},
	{	"unlink",sh_unlink},
	{	NULL,NULL}	
};
char **str2array(const char *word,char sep){
  if(word==NULL) return NULL;
  while(*word==sep) word++;
  char *path=(char*)word;
  size_t len=strlen(path);
  size_t frag=0,r=0,count=0,msize;
  char **vpath;
  /*first count how many*/
  while(*path)	if(*path++==sep) frag++;
  vpath=(char **)malloc( (frag+2)*sizeof(char*)+len+frag );
  path=(char*)word;
  vpath[r]=vpath+frag+2;
  while(*path){
	*(vpath[r]+count++)=*path++;
	if(*path==sep) {
	  *(vpath[r]+count)=(char*)NULL;
	  vpath[r+1]=vpath[r]+count+1;
	  count=0,path++,r++;
	}
  }
  vpath[r+1]=NULL;
  return vpath;
}
//first word seem to have problem
char *first_word(char *string){
	while(isspace(*string)) string++;
	size_t len=strlen(string);
	char *ret=(char*)malloc(len+1);
	if(ret==NULL) 
		{printf("cant malloc string in function firstword%d\n",len);return NULL;}
	strncpy(ret,string,len);
	ret[len]=0;
	return ret;
}
int countword(char *string){
	int count=0;
	while(*string==' ') string++;
	while(*string){
	  if(*string==0x20) count++;
	  string++;
	}
	return count;
}
int check_builtin(char *string){
	int i=0;
	char *cmd=first_word(string);
	while(list_cmd[i].name){
		if(!strcmp(list_cmd[i++].name,cmd)) return i;
	}
	return 0;
}
int do_builtin(char *string){
	int argc=countword(string);
	char **argv=str2array(string,' ');
	int i=check_builtin(string);
	if(i==0) {printf("sh:command is not found\n");goto end;}
	command_status= list_cmd[i-1].action PASS;
	end: 
	free(argv);
}
int do_external(char *string){
	return WinExec(string,SW_HIDE);
}
#define MAX_CHAR_COMMAND_LINE	4096
char *readline(const char *prompt){
	int count=0,chung=0,r=2;
	char *pt=malloc(MAX_CHAR_COMMAND_LINE);
	char *hold=pt;
	printf(prompt);
	while(chung!='\n'){
		if(count==MAX_CHAR_COMMAND_LINE) {
			r++;
			char *npt=malloc(MAX_CHAR_COMMAND_LINE*r);
			memcpy(npt,pt,count);
			pt=npt+count;
		}
		chung=getchar();
		count++;
		*pt=chung;
		pt++;
	}
	return hold;
}
int main(int argc,char **argv){
	char ch=0,r=0;
	char str[80];
	char prompt[255];
	sprintf(prompt,"%s $ ",getcwd(NULL,1024));
	char *input;
	while(true){
	  input=readline(prompt);
	  if(strlen(input)>3) {do_builtin(input);}
	  
	  free(input);
	}
	return 0;
}
